package controller;

/*
 * Action for researchers to input question for the questionnaire.
 * Used by both Binary and Network Binary type questions.
 */

import helper.DeleteCascade;
import helper.GenerateDynetml;
import helper.UserType;

import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.mybeans.dao.DAOException;

import databeans.Entity;
import databeans.EntityClass;
import databeans.MailingList;
import databeans.MailingListData;
import databeans.Question;
import databeans.Sid_Respondent;
import databeans.Survey;
import databeans.User;
import model.AnswerDAO;
import model.BinaryqDAO;
import model.ContinuousqDAO;
import model.EntityAttributeDAO;
import model.EntityClassDAO;
import model.EntityDAO;
import model.LikertqDAO;
import model.MailingListDAO;
import model.MailingListDataDAO;
import model.Model;
import model.MultipleChoiceqDAO;
import model.NumericqDAO;
import model.QuestionDAO;
import model.Sid_RespondentDAO;
import model.SocioCognitiveqDAO;
import model.SurveyDAO;

public class SurveySummaryAction extends Action {
	private SurveyDAO surveyDAO;
	private AnswerDAO answerDAO;
	private QuestionDAO questionDAO;
	private EntityClassDAO ecDAO;
	private EntityDAO entityDAO;
	private EntityAttributeDAO eaDAO;
	private BinaryqDAO binaryqDAO;
	private NumericqDAO numericqDAO;
	private LikertqDAO likertqDAO;
	private MultipleChoiceqDAO mcDAO;
	private ContinuousqDAO continuousqDAO;
	private SocioCognitiveqDAO scqDAO;
	private Sid_RespondentDAO srDAO;
	private MailingListDAO mlDAO;
	private MailingListDataDAO mldDAO;
	
	public SurveySummaryAction(Model model) {
		surveyDAO = model.getSurveyDAO();
		answerDAO = model.getAnswerDAO();
		questionDAO = model.getQuestionDAO();
		ecDAO = model.getEntityClassDAO();
		entityDAO = model.getEntityDAO();
		eaDAO = model.getEntityAttributeDAO();
		binaryqDAO = model.getBinaryqDAO();
		numericqDAO = model.getNumericqDAO();
		likertqDAO = model.getLikertqDAO();
		mcDAO = model.getMultipleChoiceqDAO();
		continuousqDAO = model.getContinuousqDAO();
		scqDAO = model.getSocioCognitiveqDAO();
		srDAO = model.getSid_RespondentDAO();
		mlDAO = model.getMailingListDAO();
		mldDAO = model.getMailingListDataDAO();
	}
	
    public String getName() {
		return "surveysummary.do";
	}
    
    public String perform(HttpServletRequest request) {

        List<String> errors = new ArrayList<String>();
        request.setAttribute("errors",errors);
        
    	// First, validate whether researcher is accessing this
    	HttpSession session = request.getSession(false);
    	User user = (User) session.getAttribute("user");
    	
    	if (user.getType() != UserType.RESEARCHER && user.getType() != UserType.RESPONDENT) {
    		errors.add("You are not a researcher or respondent!");
    		return "homepage.jsp";
    	}
    	
		String button = request.getParameter("button");
		
		if (button == null) {
			errors.add("Invalid button");
			return "researcher.jsp";
		}
		
		if (button.equals("Go Back to Researcher Menu")) {
			synchronized(session) {
				session.removeAttribute("surveylist");
				session.removeAttribute("respondentnumberlist");
				session.removeAttribute("completednumberlist");
			}
			return "researcher.jsp";
		}
		
		if (button.equals("Go Back to List of Surveys")) {
			Survey[] old_survey = null;
			try {
				if (user.getType() == UserType.RESEARCHER)
					old_survey = surveyDAO.getUserSurveys(user.getUserid());
				else
					old_survey = srDAO.getSurveyByResp(user.getUserid(), surveyDAO);
				
	    		Integer[] respondentnumberlist = new Integer[old_survey.length];
	    		Integer[] completednumberlist = new Integer[old_survey.length];
	    		
	    		for (int i = 0; i < old_survey.length; i++) {
	    			respondentnumberlist[i] = srDAO.numRespondents(old_survey[i].getSid());
	    			completednumberlist[i] = srDAO.numCompleted(old_survey[i].getSid());
	    		}
	    		
	    		synchronized(session) {
					session.setAttribute("surveylist", old_survey);
		    		session.setAttribute("respondentnumberlist", respondentnumberlist);
		    		session.setAttribute("completednumberlist", completednumberlist);
		    		session.removeAttribute("surveyend");
		    		session.removeAttribute("survey");
					session.removeAttribute("question");
					session.removeAttribute("questionlist");
	    		}
				return "viewsurvey.jsp";
			} catch (DAOException e) {
				errors.add(e.getMessage());
				return "errors.jsp";
			}
		}
		
    	if (button.equals("Create More Questions")) {
    		synchronized(session) {
    			session.removeAttribute("question");
    		}
    		return "allquestion.jsp";
    	}
    	
    	if (button.equals("MailingList")) {
    		try {
				MailingList[] ml = mlDAO.getMailingListByUserid(user.getUserid());
				if (ml == null || ml.length == 0) {
					errors.add("There are no mailing list associated with your account, please go back and create one.");
					return "surveysummary.jsp";
				}
				synchronized(session) {
					session.setAttribute("mailinglistbody", "associate");
					session.setAttribute("mailinglist", ml);
					session.setAttribute("pageFrom", "surveysummary.jsp");
				}
				return "mailinglist.jsp";
			} catch (DAOException e) {
				errors.add(e.getMessage());
				return "errors.jsp";
			}
    	}
    	
    	if (button.equals("MailingListContent")) {
    		try {
	    		Survey survey = (Survey) session.getAttribute("survey");
	    		if (survey == null) {
	    			errors.add("Invalid survey");
	    			return "errors.jsp";
	    		}
	    		
	    		MailingList ml = mlDAO.getMailingListByUseridName(user.getUserid(), survey.getMailinglist());
	    		MailingListData[] mld = mldDAO.getMailingListDataByMlid(ml.getMlid());
	    		
	    		synchronized(session) {
	    			session.setAttribute("mailinglistbody", "view");
	    			session.setAttribute("mailinglistdata", mld);
	    			session.setAttribute("pageFrom", "surveysummary.jsp");
	    		}
	    		
	    		return "mailinglist.jsp";
    		} catch (DAOException e) {
    			errors.add(e.getMessage());
    			return "errors.jsp";
    		}
    	}
    	
    	if (button.equals("ImportEntity")) {
			synchronized(session) {
				session.setAttribute("importentitybody", "init");
				session.setAttribute("pageFrom", "surveysummary.jsp");
			}
			
			return "importentity.jsp";
    	}
    	
    	if (button.equals("ImportEntityContent")) {
    		try {
    			Survey survey = (Survey) session.getAttribute("survey");
    			String ecname = request.getParameter("value");
    			EntityClass ec = ecDAO.lookupBySidName(survey.getSid(), ecname);
    			Entity[] entitylist = entityDAO.getEntityByEcid(ec.getEcid());
    			
    			synchronized(session) {
    				session.setAttribute("importentitydata", entitylist);
    				session.setAttribute("importentitybody", "view");
    				session.setAttribute("pageFrom", "surveysummary.jsp");
    			}
    			
    			return "importentity.jsp";
    		} catch (DAOException e) {
    			errors.add(e.getMessage());
    			return "errors.jsp";
    		}
    	}
    	
    	// case if coming directly from respondent url
		if (button.equals("Proceed to take the survey")) {
			try {
				Survey survey = (Survey) session.getAttribute("resp_survey");
				Question[] questionlist = questionDAO.getQuestionBySidSortedQnum(survey.getSid(), false);
				boolean[] completed = new boolean[questionlist.length];
    			for (int i = 0; i < completed.length; i++) {
    				if (answerDAO.existAnswerByQidUsername(questionlist[i].getQid(), user.getUserid()))
    					completed[i] = true;
    				else
    					completed[i] = false;
    			}
    			
	    		synchronized(session) {
	    			session.setAttribute("survey", survey);
	    			session.setAttribute("questionlist", questionlist);
	    			session.setAttribute("completedlist", completed);
	    			session.removeAttribute("resp_survey");
	    		}
	    		return "surveysummary.jsp";
			} catch (DAOException e) {
				errors.add(e.getMessage());
				return "errors.jsp";
			}
		}
		
		if (button.equals("Submit the Answers")) {
			try {
				Survey survey = (Survey) session.getAttribute("survey");
				boolean[] completed = (boolean[]) session.getAttribute("completedlist");
				
				// Check if all questions are completed
				for (int i = 0; i < completed.length; i++) {
					if (!completed[i]) {
						errors.add("There are some unfinished questions. Please go back and finish them.");
						return "surveysummary.jsp";
					}
				}
				
				// Mark the entire survey as completed
				Sid_Respondent sr = srDAO.lookup(survey.getSid(), user.getUserid());
				sr.setCompleted(1);
				srDAO.updateCompleted(sr);
				synchronized(session) {
					session.setAttribute("completesurvey", true);
				}
				return "surveysummary.jsp";
			} catch (DAOException e) {
				errors.add(e.getMessage());
				return "errors.jsp";
			}
		}
    	
		if (button.equals("Send") || button.equals("Dynetml") || button.equals("View")) {
	    	// Get the survey bean for this survey and save it as session attribute
	    	String sidStr = request.getParameter("value");
	    	if (sidStr == null) {
	    		errors.add("Invalid survey");
	    		return "researcher.jsp";
	    	}
	    	int sid = Integer.parseInt(sidStr);
	    	
	    	try {
	    		EntityClass[] eclist = ecDAO.getEntityClassBySid(sid);
	    		
		    	synchronized(session) {
		    		session.setAttribute("survey", surveyDAO.lookup(sid));
		    		session.setAttribute("entityclass", eclist);
		    	}
	    	} catch (DAOException e) {
	    		errors.add(e.getMessage());
	    		return "errors.jsp";
	    	}
			
	    	if (button.equals("Send")) { // Send survey to respondents
	    		String content = makeWebContent();
	    		synchronized(session) {
	    			session.setAttribute("content", content);
	    			session.setAttribute("sendsurvey", "init");
	    		}
	    		return "sendsurvey.jsp";
	    	}
	    	
	    	if (button.equals("Dynetml")) { // Generate dynetml
				StringBuffer sb = GenerateDynetml.generate(session, answerDAO, questionDAO, ecDAO, entityDAO, eaDAO, binaryqDAO, likertqDAO, mcDAO, scqDAO);
				System.out.println(sb.toString());
				session.setAttribute("dynetml", sb);
				return "downloaddynetml";
			}
	    	
	    	if (button.equals("View")) { // View Questions
	    		try {
	    			Question[] questionlist = questionDAO.getQuestionBySidSortedQnum(sid, true);
	    			synchronized(session) {
	    				session.setAttribute("questionlist", questionlist);
	    			}
	    			
	    			if (user.getType() == UserType.RESPONDENT) {
	    				boolean[] completed = new boolean[questionlist.length];
	    				for (int i = 0; i < completed.length; i++) {
	        				if (answerDAO.existAnswerByQidUsername(questionlist[i].getQid(), user.getUserid()))
	        					completed[i] = true;
	        				else
	        					completed[i] = false;
	        				
	        			}
	        			synchronized(session) {
	        				session.setAttribute("completedlist", completed);
	        			}
	    			}
	    			
	            	return "surveysummary.jsp";
	        	} catch (DAOException e) {
	        		errors.add(e.getMessage());
	        		return "errors.jsp";
	        	}
	    	}
	    	
	    	return null; // Unreachable code
		}
		else { // Following buttons are operations on individual questions in a survey
	    	// Get the question bean for this question and save it as session attribute
	    	String qidStr = request.getParameter("value");
	    	if (qidStr == null) {
	    		errors.add("Invalid question");
	    		return "researcher.jsp";
	    	}
	    	int qid = Integer.parseInt(qidStr);
	    	
	    	try {
		    	synchronized(session) {
		    		session.setAttribute("question", questionDAO.lookup(qid));
		    	}
	    	} catch (DAOException e) {
	    		errors.add(e.getMessage());
	    		return "errors.jsp";
	    	}
	    	
	    	Survey survey = (Survey) session.getAttribute("survey");
	    	
	    	if (button.equals("Remove")) {
	    		try {
	    			Question question = questionDAO.lookup(qid);
	    			Question[] greaterQuestion = questionDAO.getQuestionBySidQnumGreater(survey.getSid(), question.getQnum());
	    			
	    			// Delete on cascade
	    			DeleteCascade.deleteQuestion(qid, questionDAO, binaryqDAO, numericqDAO, likertqDAO, mcDAO, continuousqDAO, scqDAO);
	    			
	    			//For any questions whose question number was greater than the deleted one, move it 1 upward
	    			for (int i = 0; i < greaterQuestion.length; i++) {
	    				greaterQuestion[i].setQnum(greaterQuestion[i].getQnum() - 1);
	    				questionDAO.updateQnum(greaterQuestion[i]);
	    			}
	    			
	    			// Return new question list
	    			Question[] questionlist = questionDAO.getQuestionBySidSortedQnum(survey.getSid(), true);
	    			synchronized(session) {
	    				session.setAttribute("questionlist", questionlist);
	    			}
	            	return "surveysummary.jsp";
	    		} catch (DAOException e) {
	    			errors.add(e.getMessage());
	    			return "errors.jsp";
	    		}
	    	}
	    	
	    	if (button.equals("Modify")) {
	    		try {
	    			Question question = questionDAO.lookup(qid);
	    			int qnum = question.getQnum();
	    			
	    			// First delete, then for any questions whose question number was greater than the deleted one, move it 1 upward
	    			DeleteCascade.deleteQuestion(qid, questionDAO, binaryqDAO, numericqDAO, likertqDAO, mcDAO, continuousqDAO, scqDAO);
	    			
	    			synchronized(session) { // Mark that we are modifying this question
	    				session.setAttribute("questionmodify", qnum);
	    			}
	    			
	            	return "allquestion.jsp";
	    		} catch (DAOException e) {
	    			errors.add(e.getMessage());
	    			return "errors.jsp";
	    		}
	    	}
	    	
	    	if (button.equals("Up")) {
	    		try {
	    			Question question = questionDAO.lookup(qid);
	    			if (question.getQnum() <= 1) // Don't do anything if already at top
	    				return "surveysummary.jsp";
	    			
	    			// Swap the question number with the upper one
	    			Question upperQuestion = questionDAO.getQuestionBySidQnum(survey.getSid(), question.getQnum() - 1);
	    			question.setQnum(question.getQnum() - 1);
	    			upperQuestion.setQnum(upperQuestion.getQnum() + 1);
	    			
	    			questionDAO.updateQnum(upperQuestion);
	    			questionDAO.updateQnum(question);
	    			
	    			// Return new question list
	    			Question[] questionlist = questionDAO.getQuestionBySidSortedQnum(survey.getSid(), true);
	    			synchronized(session) {
	    				session.setAttribute("questionlist", questionlist);
	    			}
	            	return "surveysummary.jsp";
	        	} catch (DAOException e) {
	        		errors.add(e.getMessage());
	        		return "errors.jsp";
	        	}
	    	}
	    	
	    	if (button.equals("Down")) {
	    		try {
	    			Question question = questionDAO.lookup(qid);
	    			if (question.getQnum() >= questionDAO.getMaxQnumBySid(survey.getSid())) // Don't do anything if already at bottom
	    				return "surveysummary.jsp";
	    			
	    			// Swap the question number with the lower one
	    			Question lowerQuestion = questionDAO.getQuestionBySidQnum(survey.getSid(), question.getQnum() + 1);
	    			question.setQnum(question.getQnum() + 1);
	    			lowerQuestion.setQnum(lowerQuestion.getQnum() - 1);
	    			
	    			questionDAO.updateQnum(lowerQuestion);
	    			questionDAO.updateQnum(question);
	    			
	    			// Return new question list
	    			Question[] questionlist = questionDAO.getQuestionBySidSortedQnum(survey.getSid(), true);
	    			synchronized(session) {
	    				session.setAttribute("questionlist", questionlist);
	    			}
	            	return "surveysummary.jsp";
	        	} catch (DAOException e) {
	        		errors.add(e.getMessage());
	        		return "errors.jsp";
	        	}
	    	}
	    	
	    	errors.add("Illegal button value of " + button);
			return "errors.jsp";
		}
    }
    
    private synchronized String makeWebContent(){
		String messageContent = "\nWe are conducting a survey, and your response would be appreciated.\n\n"+
								 "\nHere is a link to the survey:" + "[webLink]" + "\n\n\n" +
								 "\nThis link is uniquely tied to this survey and your email address. Please do not forward this message.\n\n"+
								 "\nThanks for your participation!" + 
								 "\n\n IMS.";
		return messageContent;
	}	
}
